package com.changgou.auth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.security.KeyPair;

@Configuration
@EnableAuthorizationServer //开启认证服务
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Bean("keyProp")
    public KeyProperties keyProperties(){
        return new KeyProperties();
    }

    /*@Autowired
    @Qualifier("keyProp")*/
    @Resource(name = "keyProp")
    private KeyProperties keyProperties;

    //客户端配置信息 需要注入连接池对象 自动从数据库查询信息
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//        super.configure(clients);
        clients.jdbc(dataSource).clients(new JdbcClientDetailsService(dataSource));
    }

    //授权服务器的端点配置
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
//        super.configure(endpoints);
        endpoints.accessTokenConverter(jwtAccessTokenConverter) //设置token转换器 用于生成token
                .authenticationManager(authenticationManager)  //设置认证管理器
                .tokenStore(new JwtTokenStore(jwtAccessTokenConverter))  //令牌存储对象
                .userDetailsService(userDetailsService);  //用户信息的service
    }

    //认证服务配置 释放两个端点 用于申请令牌 校验令牌
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
//        super.configure(security);
        security.allowFormAuthenticationForClients()  //允许客户端进行表单认证
                .passwordEncoder(passwordEncoder)
                .tokenKeyAccess("permitAll()")  //允许所有的客户端发送请求申请token
                .checkTokenAccess("isAuthenticated()");

    }


    //生成token
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        //创建jwtToken转换器对象
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();

        //创建秘钥工厂对象
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(keyProperties.getKeyStore().getLocation(), keyProperties.getKeyStore().getSecret().toCharArray());

        //生成秘钥对
        KeyPair keyPair = keyStoreKeyFactory.getKeyPair(keyProperties.getKeyStore().getAlias(), keyProperties.getKeyStore().getPassword().toCharArray());

        //设置秘钥对到jwtToken转换器中
        converter.setKeyPair(keyPair);

        //设置用户信息的token转换器 获取用户信息作为载荷
        //配置自定义的CustomUserAuthenticationConverter
        DefaultAccessTokenConverter accessTokenConverter = (DefaultAccessTokenConverter) converter.getAccessTokenConverter();

        //创建默认的用户认证信息转换器
        DefaultUserAuthenticationConverter userAuthenticationConverter = new DefaultUserAuthenticationConverter();
        userAuthenticationConverter.setUserDetailsService(userDetailsService);

        //将用户信息转换器设置到token转换器中

        accessTokenConverter.setUserTokenConverter(userAuthenticationConverter);

        return converter;
    }
}
